package cn.wizzer.app.web.modules.controllers.platform.sys;

import cn.wizzer.app.sys.modules.models.Sys_role;
import cn.wizzer.app.sys.modules.models.Sys_unit;
import cn.wizzer.app.sys.modules.models.Sys_user;
import cn.wizzer.app.sys.modules.services.SysUnitService;
import cn.wizzer.app.web.commons.slog.annotation.SLog;
import cn.wizzer.app.web.commons.utils.ShiroUtil;
import cn.wizzer.app.web.commons.utils.StringUtil;
import cn.wizzer.framework.base.Result;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.dao.Cnd;
import org.nutz.dao.util.cri.SqlExpression;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.Times;
import org.nutz.lang.util.NutMap;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by wizzer on 2016/6/24.
 */
@IocBean
@At("/platform/sys/unit")
public class SysUnitController {
    private static final Log log = Logs.get();
    @Inject
    private SysUnitService sysUnitService;
    @Inject
    private ShiroUtil shiroUtil;

    @At("")
    @Ok("beetl:/platform/sys/unit/index.html")
    @RequiresPermissions("sys.manager.unit")
    public void index() {

    }

    @At("/child")
    @Ok("json")
    @RequiresAuthentication
    public Object child(@Param("pid") String pid, HttpServletRequest req) {
        List<Sys_unit> list = new ArrayList<>();
        List<NutMap> treeList = new ArrayList<>();
        if (shiroUtil.hasRole("sysadmin")) {
            Cnd cnd = Cnd.NEW();
            if (Strings.isBlank(pid)) {
                cnd.and("parentId", "=", "").or("parentId", "is", null);
            } else {
                cnd.and("parentId", "=", pid);
            }
            cnd.asc("location").asc("path");
            list = sysUnitService.query(cnd);
        } else {
            Sys_user user = (Sys_user) shiroUtil.getPrincipal();
            if (user != null && Strings.isBlank(pid)) {
                list = sysUnitService.query(Cnd.where("id", "=", user.getUnitid()).asc("path"));
            } else {
                Cnd cnd = Cnd.NEW();
                if (Strings.isBlank(pid)) {
                    cnd.and("parentId", "=", "").or("parentId", "is", null);
                } else {
                    cnd.and("parentId", "=", pid);
                }
                cnd.asc("location").asc("path");
                list = sysUnitService.query(cnd);
            }
        }
        for (Sys_unit unit : list) {
            NutMap map = Lang.obj2nutmap(unit);
            map.addv("expanded", false);
            map.addv("children", new ArrayList<>());
            treeList.add(map);
        }
        return Result.success().addData(treeList);
    }


    @At("/tree")
    @Ok("json")
    @RequiresAuthentication
    public Object tree(@Param("pid") String pid, HttpServletRequest req) {
        try {
            List<Sys_unit> list = new ArrayList<>();
            List<NutMap> treeList = new ArrayList<>();
            if (Strings.isBlank(pid)) {
                //NutMap root = NutMap.NEW().addv("value", "root").addv("label", "不选择单位");
                //treeList.add(root);
            }
            //if (shiroUtil.hasRole("sysadmin")) {
                Cnd cnd = Cnd.NEW();
                cnd.and("delFlag","=",false);
                if (Strings.isBlank(pid)) {
                    cnd.and(Cnd.exps("parentId", "=", "").or("parentId", "is", null));
                } else {
                    cnd.and("parentId", "=", pid);
                }
                cnd.asc("location").asc("path");
                list = sysUnitService.query(cnd);
            /*} else {
                Sys_user user = (Sys_user) shiroUtil.getPrincipal();
                if (user != null && Strings.isBlank(pid)) {
                    //SqlExpressionGroup group = StringUtil.dataScopeUserCnd();
                    Cnd cnd = Cnd.NEW();
                    cnd.and(group);
                    cnd.asc("path");
                    list = sysUnitService.query(cnd);
                } else {
                    Cnd cnd = Cnd.NEW();
                    if (Strings.isBlank(pid)) {
                        cnd.and("parentId", "=", "").or("parentId", "is", null);
                    } else {
                        cnd.and("parentId", "=", pid);
                    }
                    cnd.asc("location").asc("path");
                    list = sysUnitService.query(cnd);
                }
            }*/
            for (Sys_unit unit : list) {
                NutMap map = NutMap.NEW().addv("value", unit.getId()).addv("label", unit.getName());
                if (unit.isHasChildren()) {
                    map.addv("children", new ArrayList<>());
                }
                treeList.add(map);
            }
            List<String> unitss = StringUtil.dataScopeUserCnd();
            if(unitss!=null&&unitss.size()>0){
                unitss =unitss.stream().distinct().collect(Collectors.toList());
                treeList = getRoleUnitList(treeList,unitss);
            }
            return Result.success().addData(treeList);
        } catch (Exception e) {
            return Result.error();
        }
    }


    @At("/treeAll")
    @Ok("json")
    @RequiresAuthentication
    public Object treeAll(HttpServletRequest req) {
        try {
            List<NutMap> treeList = new ArrayList<>();
            Cnd cnd = Cnd.NEW();
            cnd.and(Cnd.exps("parentId", "=", "").or("parentId", "is", null));
            cnd.and("delFlag","=",false);
            cnd.asc("location").asc("path");
                List<Sys_unit> list = sysUnitService.query(cnd);
                for (Sys_unit unit : list) {
                    NutMap map = NutMap.NEW().addv("value", unit.getId()).addv("label", unit.getName());
                    if (unit.isHasChildren()) {
                        map.addv("children", getTreeList(unit.getId()));
                    }
                    treeList.add(map);
                }

            List<String> unitss = StringUtil.dataScopeUserCnd();
            if(unitss!=null&&unitss.size()>0){
                    unitss =unitss.stream().distinct().collect(Collectors.toList());
                    treeList = getRoleUnitList(treeList,unitss);
            }
            return Result.success().addData(treeList);
        } catch (Exception e) {
            return Result.error();
        }
    }

    private  List<NutMap> getRoleUnitList(List<NutMap> treeList,List<String> units){
        List<NutMap> newtreeList = new ArrayList<>();
        for(NutMap map : treeList){
            boolean flag = false;
            String id = map.get("value").toString();
            if(units.contains(id)){
                flag = true;
            }
            List<NutMap> treeChildrenList = null;
            if(map.get("children")!=null&&!flag){
                treeChildrenList = (List<NutMap>) map.get("children");
                flag = getChildren(treeChildrenList,units);
            }
            if(flag){
                //treeList.remove(map);
                if(treeChildrenList!=null) {
                    map.put("children", getRoleUnitList(treeChildrenList, units));
                }
                newtreeList.add(map);
            }
        }
        return newtreeList;
    }
    private  Boolean getChildren(List<NutMap> treeList,List<String> units){
        boolean flag = false;
        for(NutMap map : treeList){
            String id = map.get("value").toString();
            if(units.contains(id)){
                flag = true;
            }
            if(map.get("children")!=null&&!flag){
                List<NutMap> treeChildrenList =(List<NutMap>) map.get("children") ;
                flag = getChildren(treeChildrenList,units);
                if(flag){
                    continue;
                }
            }
        }
        return flag;
    }

    private List<NutMap> getTreeList(String pid){
        List<NutMap> treeList = new ArrayList<>();
        Cnd cnd = Cnd.NEW();
        cnd.and("parentId", "=", pid);
        cnd.and("delFlag","=",false);
        cnd.asc("location").asc("path");
        List<Sys_unit> list = sysUnitService.query(cnd);
        for (Sys_unit unit : list) {
            NutMap map = NutMap.NEW().addv("value", unit.getId()).addv("label", unit.getName());
            if (unit.isHasChildren()) {
                map.addv("children", getTreeList(unit.getId()));
            }
            treeList.add(map);
        }
        return treeList;
    }

    @At
    @Ok("json")
    @RequiresPermissions("sys.manager.unit.add")
    @SLog(tag = "新建单位", msg = "单位名称:${args[0].name}")
    public Object addDo(@Param("..") Sys_unit unit, @Param("parentId") String parentId, HttpServletRequest req) {
        try {
            unit.setOpBy(StringUtil.getPlatformUid());
            sysUnitService.save(unit, parentId);
            return Result.success();
        } catch (Exception e) {
            return Result.error();
        }
    }

    @At("/edit/?")
    @Ok("json")
    @RequiresPermissions("sys.manager.unit")
    public Object edit(String id, HttpServletRequest req) {
        try {
            Sys_unit unit = sysUnitService.fetch(id);
            return Result.success().addData(unit);
        } catch (Exception e) {
            return Result.error();
        }
    }

    @At
    @Ok("json")
    @RequiresPermissions("sys.manager.unit.edit")
    @SLog(tag = "编辑单位", msg = "单位名称:${args[0].name}")
    public Object editDo(@Param("..") Sys_unit unit, @Param("parentId") String parentId, HttpServletRequest req) {
        try {
            unit.setOpBy(StringUtil.getPlatformUid());
            unit.setOpAt(Times.getTS());
            sysUnitService.updateIgnoreNull(unit);
            return Result.success();
        } catch (Exception e) {
            return Result.error();
        }
    }

    @At("/delete/?")
    @Ok("json")
    @RequiresPermissions("sys.manager.unit.delete")
    @SLog(tag = "删除单位", msg = "单位名称:${args[1].getAttribute('name')}")
    public Object delete(String id, HttpServletRequest req) {
        try {
            Sys_unit unit = sysUnitService.fetch(id);
            req.setAttribute("name", unit.getName());
            if ("0001".equals(unit.getPath())) {
                return Result.error("system.not.allow");
            }
            sysUnitService.deleteAndChild(unit);
            return Result.success();
        } catch (Exception e) {
            return Result.error();
        }
    }

}
